package com.zjh.admin.websocket.handle;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

// WebSocket处理器
@Slf4j
@Component
public class DocumentWebSocketHandler extends TextWebSocketHandler {
    private static final Map<String, Set<WebSocketSession>> docSessions = new ConcurrentHashMap<>();
    private static final Map<String, String> docContents = new ConcurrentHashMap<>();
    private static final Map<String, Integer> docVersions = new ConcurrentHashMap<>();
    private static final Map<String, String> docLocks = new ConcurrentHashMap<>(); // 简单锁机制

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String docId = extractDocId(session);
        docSessions.computeIfAbsent(docId, k -> ConcurrentHashMap.newKeySet()).add(session);

        // 发送当前文档内容
        String content = docContents.getOrDefault(docId, "");
        int version = docVersions.getOrDefault(docId, 0);

        Object _username = session.getAttributes().get("username");
        String username = "";
        if (!Objects.isNull(_username)) {
            username = (String) _username;
        }
        session.sendMessage(new TextMessage(formatUpdate(content, version, username)));
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

        String docId = extractDocId(session);

        JsonNode json = new ObjectMapper().readTree(message.getPayload());
        String content = json.get("content").asText();
        int version = json.get("version").asInt();
        String senderName = json.get("username").asText();

        // 简单冲突解决：只接受版本号大于当前版本的更新
        int currentVersion = docVersions.getOrDefault(docId, 0);
        if (version > currentVersion) {
            docContents.put(docId, content);
            docVersions.put(docId, version);

            // 设置锁（最后编辑者获得锁）
            docLocks.put(docId, senderName);

            // 广播更新
            broadcastUpdate(docId, content, version, senderName);
        }
    }

    private void broadcastUpdate(String docId, String content, int version, String username) {
        Set<WebSocketSession> sessions = docSessions.get(docId);
        if (sessions != null) {
            String message = formatUpdate(content, version, username);
            sessions.forEach(session -> {
                try {
                    session.sendMessage(new TextMessage(message));
                } catch (IOException e) {
                    // 处理异常
                }
            });
        }
    }

    private String formatUpdate(String content, int version, String username) {
        return String.format("{\"content\":\"%s\",\"version\":%d,\"username\":\"%s\"}",
                escapeJson(content), version, username);
    }

    private String escapeJson(String content) {
        return content.replace("\"", "\\\"")
                .replace("\n", "\\n")
                .replace("\r", "\\r");
    }

    private String extractDocId(WebSocketSession session) {
        Object _docId = session.getAttributes().get("docId");
        String docId = "";

        if (!Objects.isNull(_docId)) {
            docId = (String) _docId;
        }

        return docId;
    }

    private String extractUsername(WebSocketSession session) {
        Object _username = session.getAttributes().get("username");
        String username = "";

        if (!Objects.isNull(_username)) {
            username = (String) _username;
        }

        return username;
    }

}